package com.dale.controller;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dale.common.dto.BlogDto;
import com.dale.common.dto.MetasDto;
import com.dale.common.lang.Result;
import com.dale.entity.Blog;
import com.dale.entity.Meta;
import com.dale.entity.MetaBlog;
import com.dale.service.BlogService;
import com.dale.service.MetaBlogService;
import com.dale.service.MetaService;
import com.dale.util.ShiroUtil;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 与分类相关
 * <p>
 * 1：管理员管理博客分类标签  （默认分类不能删除）  （限制最大分类量）
 * 2：文章分类查询
 * <p>
 * 主要维持中间表的关系  博客表没有分类属性    分类页没有博客id属性 （多对多）
 * <p>
 * 这里感觉可能会出级联问题：比如我删除了分类种类
 * 博客 分类表 也需要级联更改 把博客归属到 默认中
 *
 * @author Gyt
 * @create 2021-05-24 - 19:54
 */
@RestController
public class MetaController {

    @Autowired
    MetaService metaService;

    @Autowired
    MetaBlogService metaBlogService;  //处理 分类博客关系表

    @Autowired
    BlogService blogService;

    /**
     * 增添分类
     *
     * @return
     */
    @PostMapping("/addMeta")
    @RequiresAuthentication
    @RequiresRoles("admin")  //管理员可操作
    public Result addMeta(@RequestBody Meta meta) {

        Assert.isTrue(!StringUtils.isEmpty(meta.getName()),"空标签");

        //若分类已存在 则拒绝
        Meta byId = metaService.getById(meta.getMid());
        Assert.isTrue(byId == null, "该分类已存在");

        //进行保存
        meta.setCreated(LocalDateTime.now());
        meta.setAuthor(ShiroUtil.getProfile().getUsername());
        metaService.save(meta);
        return Result.succ(null);
    }


    /**
     * 删除分类
     *
     * @param mid
     * @return
     */
    @DeleteMapping("/delMeta")
    @RequiresAuthentication
    @RequiresRoles("admin")  //管理员可操作
    public Result delMeta(@RequestParam Long mid) {
        /*
                先把 关系表 的分类设置成默认
         */

        //首先排除是对默认分类操作
        Assert.isTrue(mid != 1L, "不能删除默认分类");

        //查出所有的该分类的 关系  注意是关系对象
        List<MetaBlog> metaBlogs = metaBlogService.list(new QueryWrapper<MetaBlog>()
                .eq("mid", mid));
//
//        //将其全部设置成默认
        for (MetaBlog metaBlog : metaBlogs) {
//            metaBlog.setMid(1L);
//            metaBlogService.save(metaBlog);
        //改为直接删除
        metaBlogService.removeById(metaBlog.getBmid());
        }



        //更改成功后 删除 分类
        metaService.removeById(mid);

        return Result.succ(null);
    }

    @RequiresRoles("admin")
    @GetMapping("/getRawMetas")
    public Result getRawMetas() {
        return Result.succ(metaService.list());
    }

    /**
     * 获得所有分类(名)
     * <p>
     * 前端要 v-for地展示分类标签
     *
     * @return
     */
    @GetMapping("/getMetas")
    public Result getMetas() {
        //前端需要的格式 数组 嵌套 label -> name
        ArrayList<String> labels = new ArrayList<>();

        List<Meta> metas = metaService.list();

        for (Meta meta : metas) {
            labels.add(meta.getName());
        }

        //labels中全是分类的名字
        return Result.succ(MapUtil.builder()
                .put("labels", labels)
                .put("count", labels.size())
                .map());
    }

    //未完待续
    /*   5-25内容：

    1 完成分类的前端模块
    2 完成分类的后台管理
    3 分类查询的动态sql逻辑
    */


    /**
     * 根据分类查找文章
     * 接收前端 传来的 分类数组 名（注意 是名字）
     *
     * @param
     * @return
     */
    @RequestMapping("/queryBlogByMeta")
    public Result queryBlogByMeta(@RequestBody MetasDto metasDto, @RequestParam(defaultValue = "1") Integer currentPage) {

        //玩死我了    json传来的 建议都封装成DTO  然后前端  注意发送过来的数据 不是form表单的要 自己手动地  给key value形式
        // this.$axios.post('/queryBlogByMeta',{"metas":this.metas}).then(res=>{


        if (metasDto.getMetas().size() == 0 || metasDto == null) {
            Page page = new Page(currentPage, 5);
            IPage pageData = blogService.selectAllBlogs(page);
            return Result.succ(pageData);
        }


        Page page = new Page(currentPage, 5);
        //注意要分页参数 玩死我了
        IPage<BlogDto> blogs = metaBlogService.queryBlogByMeta(page, metasDto.getMetas());

//        System.out.println(blogs);
        return Result.succ(blogs);
//        return null;
    }


    /**
     * 给文章分类  只用操作blog_meta表（给该表增加了分类名字属性） //远远不够  //所以还是手写sql吧
     * //还需要文章的bid
     *
     * @return
     */
    @PostMapping("/addBlogMeta")
    @RequiresRoles(value = {"common", "admin"}, logical = Logical.OR)     //表示是普通用户 或者 admin用户可访问
    public Result addBlogMeta(@RequestBody MetasDto metasDto, @RequestParam Long bid) {
        //前端发来的所有分类信息
        List metas = metasDto.getMetas();

        //这样就 给博客增加分类了
        metaBlogService.addMetaOnBlog(metas, bid);
        return Result.succ(null);
    }


    /**
     * 删除 该博客的所有 分类关系
     * 该关系不是逻辑删除  是真正的删除
     *
     * @param bid
     * @return
     */
    @DeleteMapping("/delBlogMetaByBid")
    @RequiresRoles(value = {"common", "admin"}, logical = Logical.OR)     //表示是普通用户 或者 admin用户可访问
    public Result delBlogMetaByBid(@RequestParam Long bid) {

        metaBlogService.remove(new QueryWrapper<MetaBlog>().eq("bid", bid));

        return Result.succ(null);
    }

    /**
     * 查看文章分类
     *
     * @return
     */
    @GetMapping("/queryBlogMetas")
    public Result queryBlogMetas(@RequestParam Long bid) {
        return Result.succ(metaBlogService.queryBlogMetas(bid));
    }


    /**
     * 根据分类查看文章数量
     * 可视化图
     *
     * @return
     */
    @GetMapping("/blogCountByMeta")
    public Result blogCountByMeta(@RequestParam String metaName) {
        Meta meta = metaService.getOne(new QueryWrapper<Meta>().eq("name", metaName));
        int count = metaBlogService.count(new QueryWrapper<MetaBlog>().eq("mid", meta.getMid()));

        return Result.succ(count);
    }

    /**
     * 根据分类查看文章数量
     * 可视化图
     *
     * @return
     */
    @GetMapping("/blogCountByMetas")
    public Result blogCountByMeta() {
//        Meta meta = metaService.getOne(new QueryWrapper<Meta>().eq("name", metaName));
//        int count = metaBlogService.count(new QueryWrapper<MetaBlog>().eq("mid", meta.getMid()));


        List<Meta> list = metaService.list();

//        HashMap<String, String> nameMeta = new HashMap<>();   //左边为分类属性，右边是该分类的文章数
//        HashMap<String, Integer> valueInteger = new HashMap<>();   //左边为分类属性，右边是该分类的文章数

        int metaCount = metaService.count();

//        ArrayList<Map> maps = new ArrayList<>();

        HashMap<String, Integer> map = new HashMap<>();
        for (Meta meta : list) {
            int count = metaBlogService.count(new QueryWrapper<MetaBlog>().eq("mid", meta.getMid()));
            map.put(meta.getName(), count);
        }

        return Result.succ(MapUtil.builder()
                .put("map", map)
                .put("count", metaCount)
                .map());
    }

}
